package com.ybear.ybhotrepair.core;

import android.content.Context;

import androidx.annotation.NonNull;

import com.ybear.ybhotrepair.ClassHotRepair;
import com.ybear.ybhotrepair.utils.AppUtil;
import com.ybear.ybhotrepair.utils.IOUtil;
import com.ybear.ybhotrepair.utils.LogUtil;

public class DexImpl {
    private Context mContext;
    private ClassHotRepair mClsRepair;
    private RequestManage mReq;

    private String saveDexPath;

    public DexImpl(Context context, RequestManage req) {
        mContext = context;
        mReq = req;
        mClsRepair = new ClassHotRepair( context );
        saveDexPath = mClsRepair.getLocalDexPatchDirFile().getAbsolutePath();
    }

    /**
     * 获取本地dex文件数量
     * @return      数量
     */
    public int getLocalDexFileCount() {
        return mClsRepair.getDexFileCount();
    }

    /**
     * 请求下载dex文件
     */
    public void reqDwonloadDexFile() {
        LogUtil.d("Dex file network request...");
        //查询dex文件
        new Thread(() -> mReq.queryDex((url, hash, checkID, ver) -> {
            /* 保存检查id到本地 */
            if( checkID == null ) return;
            IOUtil.saveDexCheckID(mContext, checkID);

            /* 保存校验值到本地 */
            if( hash == null ) return;
            IOUtil.saveDexHashVals(mContext, ver, hash.toArray(new String[0]));

            /* 启动下载服务 */
            if( url == null ) return;
            mReq.startDownloadService(saveDexPath, () -> {
                /* 因为dex需要在app启动时才能加载，所以下载的dex文件会在下次重启时通过本地完成加载 */
                LogUtil.d("Dex file download is complete!");
            }, url.toArray(new String[0]));
        })).start();
    }

    /**
     * 请求修复检查
     */
    public void reqCheckRepair() {
        new Thread(() -> mReq.checkRepair(dexCheckID -> {
            String localCheckID = IOUtil.readDexCheckID( mContext );
            /* dex检查id不匹配 */
            if( localCheckID == null || !localCheckID.equals( dexCheckID ) ) {
                clearLocalDexAll();
                //请求下载dex文件
                reqDwonloadDexFile();
                LogUtil.d("Check without the repair, To dex file network request...");
            }
        })).start();
    }

    /**
     * 加载dex文件
     * @param version   后台获取的补丁版本号
     */
    public void loadRepairDexFile(@NonNull String version) {
        //本地校验值
        String[] hash = IOUtil.readDexHashVals( mContext ).toArray(new String[0]);
        String appVer = AppUtil.getVerName( mContext );

        LogUtil.d("Local load dex file...");
        LogUtil.d(String.format("Local dex file version:%s, app version:%s", version, appVer));
        //dex文件版本检查
        if( version.equals( appVer ) ) {
            //加载修复的Dex文件
            int result = mClsRepair.loadRepairDexFile( hash );
            /* 修复成功 */
            if( result == ClassHotRepair.LOAD_REPAIR_DEX_SUCCESS ) {
                //保存修复成功的校验值失败
                boolean isSave = IOUtil.saveDexHashVals(mContext, version, hash);
                LogUtil.d("Repair the success! save the calibration value result:" + isSave);
            }else {
                /* 修复失败 */
                LogUtil.e("Repair the failure result:" + result);
            }
        }else {
            //清除本地所有dex
            clearLocalDexAll();
            //请求下载dex文件
            reqDwonloadDexFile();
            LogUtil.e("Repair of dex file versions do not agree with the app version! " +
                    "Will now remove the dex file and download the corresponding version.");
        }
    }

    /**
     * 清除本地所有dex
     */
    private void clearLocalDexAll() {
        //清除本地dex检查id
        IOUtil.clearDexCheckID( mContext );
        //清除本地校验值
        IOUtil.clearDexHashVal( mContext );
        //清除本地dex文件
        mClsRepair.clearDexFileAll();
    }
}
